package com.sz.biz.trade.goods.service.impl;

import com.sz.biz.common.customer.entity.CusCustomer;
import com.sz.biz.common.project.entity.Project;
import com.sz.biz.common.platform.entity.PlatformCompany;
import com.sz.biz.trade.goods.dto.*;
import com.sz.biz.trade.goods.entity.Goods;
import com.sz.biz.trade.goods.entity.GoodsProjectRel;
import com.sz.biz.trade.goods.entity.GoodsPurchaseRel;
import com.sz.biz.trade.ord.entity.TrdOrderType;
import com.sz.biz.common.AbstractVersionEntityService;
import com.sz.biz.common.customer.service.CustomerService;
import com.sz.biz.common.customer.dto.CusCustomerTradeDto;
import com.sz.biz.common.project.service.ProjectService;
import com.sz.biz.common.sup.service.SupplierService;
import com.sz.biz.common.sup.dto.SupplierDto;
import com.sz.biz.common.platform.service.PlatformCompanyService;
import com.sz.biz.trade.goods.service.GoodsProjectRelService;
import com.sz.biz.trade.goods.service.GoodsPurchaseRelService;
import com.sz.biz.trade.goods.service.GoodsService;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.utils.CollectionUtils;
import com.sz.common.base.utils.StringUtils;
import com.sz.biz.logistics.constants.ErrorCodes;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.entity.SysFile;
import com.sz.common.core.system.service.SysFileService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Function: 商品服务<br>
 * Author: jifeixing <br>
 * Date: 2017-07-12 14:10:00
 */
@Service("goodsService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class GoodsServiceImpl extends AbstractVersionEntityService implements GoodsService {

    @Autowired
    private GoodsProjectRelService goodsProjectRelService;

    @Autowired
    private GoodsPurchaseRelService goodsPurchaseRelService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private SysFileService sysFileService;

    @Autowired
    private SupplierService supplierService;

    @Autowired
    private PlatformCompanyService platformCompanyService;

    @Override
    protected String getMapperNamespace() {
        return "GoodsMapper";
    }

    /**
     * 添加商品
     * @param goodsDto
     */
    @Override
    public Integer save(GoodsDto goodsDto) throws ParseException {
        validateGoodsInfo(goodsDto);
        //平台公司还是供应商
        Integer supplierType = populateSupplierType(goodsDto.getSupplierCode());
        goodsDto.setSupplierType(supplierType);

        Goods goods = new Goods();
        BeanUtils.copyProperties(goodsDto, goods);
        goods.setCode(generateCode());
        goods.setCreateUserId(PrincipalUtils.getAccountId());
        goods.setLastUpdateUserId(PrincipalUtils.getAccountId());
        super.save(goods);
        //保存采购限制
        savePurchaseCustomers(goodsDto, goods.getId());
        //保存项目限制
        saveProjects(goodsDto, goods.getId());
        return goods.getId();
    }

    /**
     * 生成商品编码
     * @return
     */
    private synchronized String generateCode(){
        //三位编码
        String code = "001";
        //获取数据库最新
        String lastTaskCode = getLastCode(null);
        if(!StringUtils.isEmpty(lastTaskCode)){
            code = populateSuffix(lastTaskCode, 3);
        }
        //新的任务编码是否已经存在
        String newTaskCodeIsExist = getLastCode(code);
        if(!StringUtils.isEmpty(newTaskCodeIsExist)){
            generateCode();
        }
        return code;
    }

    /**
     * 不够位数的在前面补0，保留num的长度位数字
     * @param code
     * @return
     */
    private static String populateSuffix(String code, int num) {
        String result = String.format("%0" + num + "d", Integer.parseInt(code) + 1);
        return result;
    }

    /**
     * 最后的商品编码
     * @param code
     * @return
     */
    private String getLastCode(String code) {
        ParamData paramData = new ParamData();
        paramData.put("code", code);
        return (String) dao.findForObject(getSqlName("getLastCode"), paramData);
    }

    /**
     * 保存限定企业
     * @param goodsDto
     * @param goodsId
     */
    private void savePurchaseCustomers(GoodsDto goodsDto, Integer goodsId){
        if(null != goodsDto && goodsDto.getPurchaserLimit().compareTo(1) == 0){
            List<String> purchaseCustomerCodes = goodsDto.getPurchaserCustomerCodes();
            if(null != purchaseCustomerCodes && purchaseCustomerCodes.size() > 0){
                for(String customerCode : purchaseCustomerCodes){
                    GoodsPurchaseRel goodsPurchaseRel = new GoodsPurchaseRel();
                    goodsPurchaseRel.setGoodsId(goodsId);
                    goodsPurchaseRel.setCustomerCode(customerCode);
                    goodsPurchaseRelService.save(goodsPurchaseRel);
                }
            }
        }
    }

    /**
     * 保存限定项目
     * @param goodsDto
     * @param goodsId
     */
    private void saveProjects(GoodsDto goodsDto, Integer goodsId){
        if(null != goodsDto && goodsDto.getProjectLimit().compareTo(1) == 0){
            List<Integer> goodsProjectIds = goodsDto.getProjectIds();
            if(null != goodsProjectIds && goodsProjectIds.size() > 0){
                for(Integer projectId : goodsProjectIds){
                    GoodsProjectRel goodsProjectRel = new GoodsProjectRel();
                    goodsProjectRel.setProjectId(projectId);
                    goodsProjectRel.setGoodsId(goodsId);
                    goodsProjectRelService.save(goodsProjectRel);
                }
            }
        }
    }

    /**
     * 商品列表
     * @param params
     * @return
     */
    @Override
    public QResultDto findByFilter(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        List<GoodsListDto> goodsListDtos = dao.findForList(getSqlName("findByFilterListPage"), pd, GoodsListDto.class);
        if(null != goodsListDtos && goodsListDtos.size() > 0){
            goodsListDtos.forEach(goodsListDto -> {
                if(null != goodsListDto){
                    //项目限制
                    if(goodsListDto.getProjectLimit().compareTo(1) == 0){
                        List<ProjectGoodsDto> projectGoodsDtos = getLimitProjects(goodsListDto.getId());
                        goodsListDto.setProject(projectGoodsDtos);
                    }
                    //采购限制
                    if(goodsListDto.getPurchaserLimit().compareTo(1) == 0){
                        List<CusCustomerTradeDto> customers = getLimitPurchases(goodsListDto.getId());
                        goodsListDto.setPurchaserCustomer(customers);
                    }
                }
            });
        }
        return new QResultDto(goodsListDtos, pd.getPagination());
    }

    /**
     * 获取商品图片
     * @param imageId
     * @return
     */
    private String goodsImage(String imageId){
        String imageUrl = null;
        //商品图片
        if(StringUtils.isEmpty(imageId)){
            SysFile sysFile = sysFileService.getFileInfo(imageId);
            if(null != sysFile){
                imageUrl = sysFile.getFileLocation();
            }
        }
        return imageUrl;
    }

    /**
     * 指定的采购商
     * @param goodsId
     * @return
     */
    private List<CusCustomerTradeDto> getLimitPurchases(Integer goodsId){
        List<CusCustomerTradeDto> customerList = new ArrayList<>();
        List<String> purchaseCustomerCodes = goodsPurchaseRelService.findPurchaseCustomerIdsByGoodsId(goodsId);
        if(null != purchaseCustomerCodes && purchaseCustomerCodes.size() > 0){
            //客户信息
            List<CusCustomerTradeDto> customers = customerService.findCustomerTrade(purchaseCustomerCodes);
            if(!CollectionUtils.isEmpty(customers)){
                customerList.addAll(customers);
            }
            //平台信息
            List<CusCustomerTradeDto> platforms = platformCompanyService.findByCodes(purchaseCustomerCodes);
            if(!CollectionUtils.isEmpty(platforms)){
                customerList.addAll(platforms);
            }
        }
        return customerList;
    }
    /**
     * 获取限定项目信息
     * @param goodsId
     * @return
     */
    private List<ProjectGoodsDto> getLimitProjects(Integer goodsId){
        List<ProjectGoodsDto> projectGoodsDtos = new ArrayList();
        List<Integer> projectIds = goodsProjectRelService.findProjectIdsByGoodsId(goodsId);
        if(null != projectIds && projectIds.size() > 0){
            List<Project> projects = projectService.findByIds(projectIds);
            if(null != projects && projects.size() > 0){
                for(Project project : projects){
                    ProjectGoodsDto projectGoodsDto = new ProjectGoodsDto();
                    BeanUtils.copyProperties(project, projectGoodsDto);
                    projectGoodsDtos.add(projectGoodsDto);
                }
            }
        }
        return projectGoodsDtos;
    }
    /**
     * 批量删除商品
     * @param ids
     */
    @Override
    public void batchDeleteByIds(List<Integer> ids) {
        if (null == ids || ids.size() <= 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL, "");
        }
        ParamData paramData = new ParamData();
        paramData.put("ids", ids);
        dao.delete(getSqlName("batchDeleteByIds"), paramData);
        for(Integer goodsId : ids){
            //删除采购限企业
            goodsPurchaseRelService.deleteByGoodsId(goodsId);
            //删除采购项目限定
            goodsProjectRelService.deleteByGoodsId(goodsId);
        }
    }
    /**
     * 编辑商品
     * @param goodsDto
     */
    @Override
    public void update(GoodsDto goodsDto) {
        validateGoodsInfo(goodsDto);
        Integer supplierType = populateSupplierType(goodsDto.getSupplierCode());
        goodsDto.setSupplierType(supplierType);
        Goods goods = new Goods();
        BeanUtils.copyProperties(goodsDto, goods);
        goods.setLastUpdateUserId(PrincipalUtils.getAccountId());
        dao.update(getSqlName("updateSelective"), goods);
        updateGoodsLimit(goodsDto);
    }

    /**
     * 验证商品添加和修改信息
     * @param goodsDto
     */
    private void validateGoodsInfo(GoodsDto goodsDto){
        if(null == goodsDto || StringUtils.isEmpty(goodsDto.getName()) || null == goodsDto.getGoodsTypeId() ||
                null == goodsDto.getPrice() || null == goodsDto.getCurrencyType() || StringUtils.isEmpty(goodsDto.getUnit()) || null == goodsDto.getSupplierId()){
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL, "");
        }
        //验证商品项目限制
        Integer projectLimit = goodsDto.getProjectLimit();
        if(null != projectLimit && projectLimit.compareTo(1) == 0){
            List<Integer> projectIds = goodsDto.getProjectIds();
            if(CollectionUtils.isEmpty(projectIds)){
                throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL, "");
            }
        }
        //验证商品企业限制
        Integer purchaserLimit = goodsDto.getPurchaserLimit();
        if(null != purchaserLimit && purchaserLimit.compareTo(1) == 0){
            List<String> purchaserCustomerCodes = goodsDto.getPurchaserCustomerCodes();
            if(CollectionUtils.isEmpty(purchaserCustomerCodes)){
                throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL, "");
            }
        }
    }

    /**
     * 商品属于平台还是供应商
     * @param supplierCode
     * @return
     */
    private Integer populateSupplierType(String supplierCode){
        Integer supplierType = 1;
        //是否是平台公司
        PlatformCompany platformCompany = platformCompanyService.findByCode(supplierCode);
        if(null != platformCompany){
            return 2;
        }
        return supplierType;
    }
    /**
     * 根据id获取商品信息
     * @param id
     * @return
     */
    @Override
    public GoodsInfoDto findById(Integer id) {
        GoodsInfoDto goodsInfoDto = (GoodsInfoDto) dao.findForObject(getSqlName("findById"), id);
        if(null != goodsInfoDto){
            //获取限定项目
            if(null != goodsInfoDto.getProjectLimit() && goodsInfoDto.getProjectLimit().compareTo(1) == 0){
                List<ProjectGoodsDto> projectGoodsDtos = getLimitProjects(goodsInfoDto.getId());
                goodsInfoDto.setProject(projectGoodsDtos);
            }
            if(null != goodsInfoDto.getPurchaserLimit() && goodsInfoDto.getPurchaserLimit().compareTo(1) == 0){
                List<CusCustomerTradeDto> customers = getLimitPurchases(goodsInfoDto.getId());
                goodsInfoDto.setPurchaserCustomer(customers);
            }
        }
        return goodsInfoDto;
    }
    /**
     * 商品启用停用
     * @param map
     */
    @Override
    public Boolean enableByIds(Map<String, Object> map) {
        if(null == map || map.isEmpty()){
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL, "");
        }
        List<Integer> goodsIds = (List<Integer>) map.get("ids");
        Boolean isEnabled = (Boolean) map.get("isEnabled");
        if(null == goodsIds || goodsIds.size() <= 0 || null == isEnabled){
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL, "");
        }

        ParamData paramData = new ParamData();
        paramData.put("goodsIds", goodsIds);
        paramData.put("isEnabled", isEnabled);
        dao.update(getSqlName("enableByIds"), paramData);
        return isEnabled;
    }

    /**
     * 客户平台订单列表商品过滤条件初始化
     * @param q
     * @param businessType
     * @param orderType
     * @param sellId
     * @param purchaserId
     * @param pageIndex
     * @param pageSize
     * @param sort
     * @param asc
     * @return
     */
    @Override
    public QResultDto findGoodsShortListCustomer(String q, Integer businessType, TrdOrderType orderType, Integer sellId, Integer purchaserId, int pageIndex, int pageSize, String sort, Boolean asc){
        q = StringUtils.replaceSqlPattern(q);
        QueryParams params = new QueryParams(pageSize, pageIndex, q, sort, asc);
        params.put("businessType", businessType);
        //根据订单类型、销售方、采购方获取所属项目
        params.put("orderType", orderType.getCode());
        params.put("supplierId", sellId);
        if(orderType.getCode().equals(TrdOrderType.PURCHASE.getCode())){
            //换取供应商信息
            SupplierDto supplierDto = supplierService.findCurrTrdSupplier();
            if(null != supplierDto){
                params.put("supplierId", supplierDto.getId());
            }
        }
        params.put("q", q);
        ParamData pd = convertQueryParams(params);
        List<GoodsListShortDto> goodsListDtos = dao.findForList(getSqlName("findByFilterListPageShortCustomer"), pd, GoodsListShortDto.class);
        return new QResultDto(goodsListDtos, pd.getPagination());
    }

    /**
     * 商品列表,返回id,code,name
     * @param q
     * @param businessType
     * @param orderType
     * @param goodsTypeId
     * @param projectId
     * @param purchaserId
     * @param pageIndex
     * @param pageSize
     * @param sort
     * @param asc
     * @return
     */
    @Override
    public QResultDto findGoodsShortList(String q, Integer businessType, TrdOrderType orderType, Integer goodsTypeId, Integer projectId, Integer sellId, Integer purchaserId, int pageIndex, int pageSize, String sort, Boolean asc) {
        q = StringUtils.replaceSqlPattern(q);
        QueryParams params = new QueryParams(pageSize, pageIndex, q, sort, asc);
        params.put("businessType", businessType);
        params.put("goodsTypeId", goodsTypeId);
        //根据订单类型、销售方、采购方获取所属项目
        String orderTypeName = null;
        if(null != orderType){
            orderTypeName = orderType.name();
            params.put("orderType", orderType.getCode());
            //销售订单-限制采购企业为客户
            if(orderType.getCode().equals(TrdOrderType.SALE.getCode())){
                CusCustomer cusCustomer = customerService.findCustomerById(purchaserId);
                if(null != cusCustomer){
                    params.put("purchaserCode", cusCustomer.getCode());
                }
            }else{  //采购订单-限制采购企业为平台
                PlatformCompany platformCompany = platformCompanyService.getPlatformCompanyById(purchaserId);
                if(null != platformCompany){
                    params.put("purchaserCode", platformCompany.getCode());
                }
            }
        }
        List<Integer> projectIds = new ArrayList<>();
        if(null == projectId){
            List<Project> projects = projectService.findSimpleProjects(orderTypeName, sellId, purchaserId);
            if(null != projects && projects.size() > 0){
                for(Project project : projects){
                    projectIds.add(project.getId());
                }
            }
            if(projectIds.size() > 0){
                params.put("projectIds", projectIds);
            }
        }else{
            projectIds.add(projectId);
            params.put("projectIds", projectIds);
        }
        params.put("supplierId", sellId);
        params.put("purchaserId", purchaserId);
        params.put("q", q);
        ParamData pd = convertQueryParams(params);
        List<GoodsListShortDto> goodsListDtos = dao.findForList(getSqlName("findByFilterListPageShort"), pd, GoodsListShortDto.class);
        return new QResultDto(goodsListDtos, pd.getPagination());
    }

    @Override
    public QResultDto findByFilterCustomer(String q, Integer businessType, TrdOrderType orderType, String goodsTypeId, Integer projectId, Integer sellId, Integer purchaserId, int pageIndex, int pageSize, String sort, Boolean asc) {
        q = StringUtils.replaceSqlPattern(q);
        QueryParams params = new QueryParams(pageSize, pageIndex, q, sort, asc);
        params.put("businessType", businessType);
        List<Integer> goodTypes = splitGoodTypeIds(goodsTypeId);
        if (goodTypes.size() > 0) {
            params.put("goodsTypeIds", goodTypes);
        }
        //根据订单类型、销售方、采购方获取所属项目
        String orderTypeName = null;
        if(null != orderType){
            orderTypeName = orderType.name();
            params.put("orderType", orderType.getCode());
            //销售订单-限制采购企业为客户
            if(orderType.getCode().equals(TrdOrderType.SALE.getCode())){
                CusCustomer cusCustomer = customerService.findCustomerById(purchaserId);
                if(null != cusCustomer){
                    params.put("purchaserCode", cusCustomer.getCode());
                }
            }else{  //采购订单-限制采购企业为平台
                PlatformCompany platformCompany = platformCompanyService.getPlatformCompanyById(purchaserId);
                if(null != platformCompany){
                    params.put("purchaserCode", platformCompany.getCode());
                }
            }
        }
        List<Integer> projectIds = new ArrayList<>();
        if(null == projectId){
            List<Project> projects = projectService.findSimpleProjects(orderTypeName, sellId, purchaserId);
            if(null != projects && projects.size() > 0){
                for(Project project : projects){
                    projectIds.add(project.getId());
                }
            }
            if(projectIds.size() > 0){
                params.put("projectIds", projectIds);
            }
        }else{
            projectIds.add(projectId);
            params.put("projectIds", projectIds);
        }
        params.put("supplierId", sellId);
        params.put("purchaserId", purchaserId);
        params.put("q", q);
        ParamData pd = convertQueryParams(params);
        List<GoodsListCustomerDto> goodsListDtos = dao.findForList(getSqlName("findByFilterCustomerGoodsListPage"), pd, GoodsListCustomerDto.class);
        return  new QResultDto(goodsListDtos, pd.getPagination());
    }

    @Override
    public List<GoodsListCustomerDto> findGoodsListByIds(String ids) {
        ParamData pd = new ParamData();
        List<Integer> listIds = splitGoodTypeIds(ids);
        if (listIds.size() <= 0) {
            return null;
        }
        pd.put("ids", listIds);
        List<GoodsListCustomerDto> goodsListDtos = dao.findForList(getSqlName("findGoodsListByIds"), pd, GoodsListCustomerDto.class);
        return goodsListDtos;
    }

    private List<Integer> splitGoodTypeIds(String goodTypeIds) {
        List<Integer> goodTypes = new ArrayList<>();
        if (!StringUtils.isEmpty(goodTypeIds)) {
            String[] strs = goodTypeIds.split(",");
            if (strs != null) {
                for (String str : strs) {
                    if (StringUtils.isNumber(str)) {
                        goodTypes.add(Integer.parseInt(str));
                    }

                }
            }
        }
        return goodTypes;
    }

    /**
     * 商品列表,返回订单需要字段
     * @param goodsId
     * @return
     */
    @Override
    public GoodsInfoShortDto findShortById(Integer goodsId) {
        GoodsInfoShortDto goodsInfoShortDto = (GoodsInfoShortDto) dao.findForObject(getSqlName("findShortById"), goodsId);
        return goodsInfoShortDto;
    }

    /**
     * 同步商品项目限制，企业限制
     * @param goodsDto
     */
    private void updateGoodsLimit(GoodsDto goodsDto){
        //删除采购限企业
        goodsPurchaseRelService.deleteByGoodsId(goodsDto.getId());
        //删除采购项目限定
        goodsProjectRelService.deleteByGoodsId(goodsDto.getId());
        //保存采购限制
        savePurchaseCustomers(goodsDto, goodsDto.getId());
        //保存项目限制
        saveProjects(goodsDto, goodsDto.getId());
    }
}
